home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994…tember: Reference Library / Dev.CD Sep 94.toast / Periodicals / develop / develop Issue 19 / develop 19 code / SimpliFace_V2 / Sources / ScriptableObjects.cp < prev    next >
Encoding:
Text File  |  1994-05-01  |  24.2 KB  |  1,063 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ScriptableObjects.cp
  3.  
  4.     Contains:    Script handling & OSA interface
  5.  
  6.  
  7.     Developed by:
  8.  
  9.     Paul G Smith (commstalk hq & Full Moon Software, Inc)
  10.  
  11.     you can leave messages at (UK): 0727 844232; (US): 408 253 7199
  12.     BUT I prefer to be contacted by e-mail
  13.     AppleLink:     COMMSTALK.HQ
  14.     Internet:     COMMSTALK.HQ@applelink.apple.com
  15.  
  16.     "SimpliFace2" Sample code to accompany develop article
  17.     on techniques for controlling script inheritance.
  18.     
  19.     
  20.  
  21.  
  22.     
  23.  
  24. */
  25.  
  26.  
  27. #include "ScriptableObjects.h"
  28. #include "SimpliFace2Common.h"
  29.  
  30. #ifndef __STDIO__
  31. #include <StdIO.h>
  32. #endif
  33.  
  34. #ifndef __LIMITS__
  35. #include <Limits.h>
  36. #endif
  37.  
  38. #ifndef __ERRORS__
  39. #include <Errors.h>
  40. #endif
  41.  
  42. #ifndef __RESOURCES__
  43. #include <Resources.h>
  44. #endif
  45.  
  46. #ifndef __TOOLUTILS__
  47. #include <ToolUtils.h>
  48. #endif
  49.  
  50. #ifndef __FOLDERS__
  51. #include <Folders.h>
  52. #endif
  53.  
  54. #ifndef __PLSTRINGFUNCS__
  55. #include <PLStringFuncs.h>
  56. #endif
  57.  
  58. #ifndef __WINDOWS__
  59. #include <Windows.h>
  60. #endif
  61.  
  62. #ifndef __PACKAGES__
  63. #include <Packages.h>
  64. #endif
  65.  
  66. #ifndef __PROCESSES__
  67. #include <Processes.h>
  68. #endif
  69.  
  70. #ifndef __PLSTRINGFUNCS__
  71. #include <PLStringFuncs.h>
  72. #endif
  73.  
  74. #ifndef __AEOBJECTS__
  75. #include <AEObjects.h>
  76. #endif
  77.  
  78. #ifndef __ASDEBUGGING__
  79. #include <ASDebugging.h>
  80. #endif
  81.  
  82. #ifndef __ASREGISTRY__
  83. #include <ASRegistry.h>
  84. #endif
  85.  
  86. #ifndef __SCRIPTUTILS__
  87. #include "ScriptUtils.h"
  88. #endif
  89.  
  90. #ifndef __SimpliFace2__
  91. #include "SimpliFace2.h"
  92. #endif
  93.  
  94. #ifndef __AEOMTOKENS__
  95. #include "ObjModelTokens.h"
  96. #endif
  97.  
  98. #ifndef __AEOMEVENTS__
  99. #include "ObjModelEvents.h"
  100. #endif
  101.  
  102.  
  103. #include "DebugTrace.h"
  104.  
  105. #pragma trace off
  106.  
  107. // globals
  108.  
  109.  
  110. TScriptAdministrator*    gScriptAdministrator = NULL;
  111. ComponentInstance        gScriptingComponent = NULL;
  112. AEAddressDesc            gSelfAddress;
  113. ProcessSerialNumber        gSelfPSN;
  114.  
  115.  
  116. #ifndef kComponentNotFound
  117. #define kComponentNotFound -1
  118. #endif
  119.     
  120.  
  121.  
  122.  
  123. OSAError GetOSAerrorInfo(ComponentInstance scriptingSystem,
  124.                              OSAError *errNum, char *errStr)
  125. {
  126.     OSAError     err = 0;
  127.     AEDesc        infoDesc;
  128.     
  129.     *errNum = 0;
  130.     
  131.     err = OSAScriptError(scriptingSystem, kOSAErrorMessage,
  132.                          typeChar, &infoDesc);
  133.     if (err == noErr)
  134.         GetPStringFromDescriptor(&infoDesc, errStr);
  135.         
  136.     err = OSAScriptError(scriptingSystem, kOSAErrorNumber,
  137.                          typeShortInteger, &infoDesc);
  138.     if (err == noErr)
  139.         GetLongIntFromDescriptor(&infoDesc, errNum);
  140.  
  141.     return err;
  142. }
  143.  
  144.  
  145.  
  146. void DumpOSAerrorInfo(ComponentInstance scriptingSystem, OSAError err)
  147. {
  148.     char        message[256];
  149.     OSAError    newerr = 0, errNum;
  150.     
  151.     if (err == errOSAScriptError)
  152.     {
  153.         memset(message, 0, 256);
  154.         
  155.         newerr = GetOSAerrorInfo(scriptingSystem, &errNum, message);
  156.     
  157.         if (!newerr /*&& errNum*/ )
  158.         {
  159.             printf("DumpOSAerrorInfo: errNum = %ld\n", errNum);
  160.             printf("%s\n", &message[1]);
  161.         }
  162.         else
  163.             printf("DumpOSAerrorInfo failed: err = %ld\n", err);
  164.     }
  165. }
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172. pascal OSErr StdActiveProc(long refCon)
  173. {
  174.     if (gSimpliFace2 && gScriptAdministrator)
  175.     {
  176.         if (!gScriptAdministrator->StartupScriptIsRunning())
  177.             gSimpliFace2->InEventLoop();
  178.     }
  179.     return 0;
  180. }
  181.  
  182.  
  183. /*
  184.     Name:   InitOSAScripting
  185.     Purpose:Connects to the AppleScript component.
  186. */
  187. OSAError InitOSAScripting(void)
  188. {
  189.     OSAError                 err = 0;
  190.     ComponentDescription     descr;
  191.     Component               aComponent;
  192.     ProcessSerialNumber        aSelfPSN;
  193.     ComponentInstance         aScriptingComponent;
  194.     AEAddressDesc            aSelfAddress;    // A self-addressed address descriptor record
  195.     
  196.      aSelfPSN.highLongOfPSN = 0;
  197.      aSelfPSN.lowLongOfPSN = kCurrentProcess;        //* Use this instead of GetCurrentProcess *//
  198.     AECreateDesc(typeProcessSerialNumber, (Ptr)&aSelfPSN,
  199.                  sizeof(ProcessSerialNumber), &aSelfAddress);
  200.  
  201.     descr.componentType         = kOSAComponentType;
  202.     descr.componentSubType      = (OSType) 0;
  203.     descr.componentManufacturer = (OSType) 0;
  204.     descr.componentFlags        = kOSASupportsCompiling + 
  205.                                   kOSASupportsGetSource + 
  206.                                   kOSASupportsConvenience + 
  207.                                   kOSASupportsEventHandling;
  208.     descr.componentFlagsMask    = descr.componentFlags;
  209.     
  210.     aComponent = FindNextComponent(nil, &descr);
  211.         
  212.     if (!aComponent)
  213.         return(kComponentNotFound);
  214.     else
  215.     {
  216.         aScriptingComponent = OpenComponent(aComponent);
  217.                                                                                                 
  218.         if (!aScriptingComponent)
  219.             return(kComponentNotFound);
  220.  
  221.         err = OSASetActiveProc(aScriptingComponent, 
  222.                                 (OSAActiveProcPtr)&StdActiveProc, 0);
  223.     //    if (err == noErr)
  224.     //        err = OSASetResumeDispatchProc(aScriptingComponent, 
  225.     //                                        kOSAUseStandardDispatch, 
  226.     //                                        kOSADontUsePhac);
  227.     }
  228.         
  229.     gScriptingComponent = aScriptingComponent;
  230.     gSelfAddress = aSelfAddress;
  231.     gSelfPSN = aSelfPSN;
  232.     
  233.     return err;
  234. }
  235.  
  236.  
  237. /*
  238.     Name    : CloseOSAScripting
  239.     Purpose : Shutdown of OSA scripting capabilities
  240. */
  241. OSAError CloseOSAScripting(void)
  242. {
  243.     OSAError err = noErr;
  244.     
  245.     if (gScriptingComponent)
  246.     {
  247.         err = CloseComponent(gScriptingComponent);
  248.         gScriptingComponent = NULL;
  249.     }
  250.     
  251.     return err;
  252. }
  253.  
  254.  
  255.  
  256. OSAError StartScriptAdministrator(void)
  257. {
  258.     OSAError    err = InstallEventHandlers();
  259.     
  260.     if (err == noErr)
  261.         err = SFinitAEobjects();
  262.     if (err == noErr)
  263.         err = InitOSAScripting();
  264.     
  265.     if (err == noErr)
  266.         gScriptAdministrator = new TScriptAdministrator;
  267.     
  268.     return err;
  269. }
  270.  
  271.  
  272. OSAError StopScriptAdministrator(Boolean saveGlobals)
  273. {
  274.     OSAError    err = noErr;
  275.     
  276.     if (gScriptAdministrator)
  277.     {
  278.         if (saveGlobals)
  279.             gScriptAdministrator->SaveGlobalVariables();
  280.         delete gScriptAdministrator;
  281.         gScriptAdministrator = NULL;
  282.     }
  283.     
  284.     err = SFendAEobjects();
  285.     err = DeInstallEventHandlers();
  286.     err = CloseOSAScripting();
  287.         
  288.     return err;
  289. }
  290.  
  291.  
  292.  
  293. /*******************************************************************************
  294. ** PUBLIC Constructor/Destructor
  295. ********************************************************************************/
  296.  
  297. TScriptAdministrator::TScriptAdministrator() 
  298.         : TScriptableObject(NULL)
  299. {
  300.     AEDesc                contextName;
  301.     
  302.     fSharedScript = kOSANullScript;
  303.     if (gScriptingComponent)
  304.     {
  305.         // The following two statements create an empty 'shared handlers'
  306.         // script that is a property of the application object.
  307.         OSAID newScriptID = kOSANullScript;
  308.         InitAEDescs(&contextName, kEndOfList);
  309.         OSAError err = OSAMakeContext(gScriptingComponent, &contextName,
  310.                                         kOSANullScript, &newScriptID);
  311.         if (err == noErr)
  312.         {
  313.             fSharedScript = newScriptID;
  314.             printf("created shared script %ld\n", newScriptID);
  315.         }
  316.         else
  317.             printf("failed to create shared script: err = %ld\n", err);
  318.     }
  319.     fStartupScriptRunning = false;
  320.     
  321.     LoadGlobalVariables();
  322. }
  323.  
  324.  
  325. TScriptAdministrator::~TScriptAdministrator(void)
  326. {
  327.     if (gScriptingComponent && fSharedScript != kOSANullScript)
  328.         OSADispose(gScriptingComponent, fSharedScript);
  329. }
  330.  
  331.  
  332.  
  333. void TScriptAdministrator::LoadGlobalVariables(void)
  334. {
  335.     OSAError            err = noErr;
  336.     OSAID                newScript = kOSANullScript;
  337.     FSSpec                 theFileSpec;
  338.     
  339.     printf("::LoadGlobalVariables()");
  340.     
  341.     err = FindFolder(0, kPreferencesFolderType, kDontCreateFolder,
  342.                      &theFileSpec.vRefNum, &theFileSpec.parID);
  343.     
  344.     if (err == noErr)
  345.     {
  346.         Str255                 fileName;
  347.         
  348.         GetIndString(fileName, kSimpliFace2Buzzwords, kPreferencesFileName);
  349.         PLstrcpy((StringPtr)&(theFileSpec.name), (ConstStr255Param)fileName);
  350.         
  351.         // now try to load our saved global variables context
  352.         err = LoadScriptFromFile(&theFileSpec, &newScript);
  353.         
  354.         fPrefsFileSpec = theFileSpec;
  355.     }
  356.     
  357.     if (err || newScript == kOSANullScript) 
  358.     {    // we failed; simply create new context for global variables
  359.         AEDesc                contextName;
  360.         
  361.         InitAEDescs(&contextName, kEndOfList);
  362.         err = OSAMakeContext(gScriptingComponent, &contextName,
  363.                                 kOSANullScript, &newScript);
  364.     }
  365.     
  366.     if (err == noErr)
  367.     {
  368.         if (fAttachedScript)    // throw away any existing global vars script
  369.             OSADispose(gScriptingComponent, fAttachedScript);            
  370.         fAttachedScript = newScript;
  371.         printf("; glob vars script %ld", fAttachedScript);
  372.     }
  373.     printf("; err = %ld\n", err);
  374. }
  375.  
  376.  
  377. void TScriptAdministrator::SaveGlobalVariables(void)
  378. {
  379.     if (fAttachedScript != kOSANullScript)
  380.     {
  381.         FSSpec                 theFileSpec = fPrefsFileSpec;
  382.         OSAError            err = noErr;
  383.         
  384.         printf("TScriptAdministrator::SaveGlobalVariables()");
  385.     
  386.         // try to save our saved global variables context
  387.         err = SaveScriptToFile(&theFileSpec, fAttachedScript);
  388.         
  389.         printf("; err = %ld\n", err);
  390.     }
  391. }
  392.  
  393.  
  394. void TScriptAdministrator::RunStartupScript(void)
  395. {
  396.     if (fStartupScriptRunning)
  397.         printf("•TScriptAdministrator::RunStartupScript(): attempt to run script recursively\n");
  398.     else
  399.     {
  400.         Str255                fileName;
  401.         short                appVRefNum;
  402.         long                appDirID;
  403.         OSAError            err = GetCurrentAppFileSpec(&appVRefNum, &appDirID,
  404.                                                         (StringPtr)&fileName);
  405.         
  406.         printf("TScriptAdministrator::RunStartupScript()\n");
  407.         
  408.         fStartupScriptRunning = true;
  409.     
  410.         if (err == noErr)
  411.         {
  412.             FSSpec                 theFileSpec;
  413.             OSAID                startupScript = kOSANullScript;
  414.     
  415.             GetIndString(fileName, kSimpliFace2Buzzwords, kStartupScriptFileName);
  416.             
  417.             theFileSpec.vRefNum = appVRefNum;
  418.             theFileSpec.parID = appDirID;
  419.             PLstrcpy((StringPtr)&(theFileSpec.name), (ConstStr255Param)fileName);
  420.             
  421.             err = LoadScriptFromFile(&theFileSpec, &startupScript);
  422.             
  423.             if (err == noErr && startupScript != kOSANullScript)
  424.             {
  425.                 OSAID                resultID = kOSANullScript;
  426.     
  427.                 err = OSAExecute(gScriptingComponent, startupScript,
  428.                                     kOSANullScript, kOSAModeNull, &resultID);
  429.                     // •• we can't execute the startup script in our
  430.                     // global variables context (so globals cannot be
  431.                     // shared) because AS ignores the context supplied
  432.                     // if the script being executed is itself a context
  433.                     // • an alternative might be to attach the loaded script 
  434.                     // as a temporary parent of the global variables
  435.                     // script, and set the parent of the loaded script to
  436.                     // be the shared handlers script: this won't work either
  437.                     // because the default 'run' handler in the global
  438.                     // variables script doesn't continue the 'run' message
  439.                     // (so our loaded script will never see it)
  440.                     
  441.                 if (err)
  442.                     DumpOSAerrorInfo(gScriptingComponent, err);
  443.                 else
  444.                 {
  445.                     AEDesc        displayData;
  446.                     
  447.                     printf("TScriptAdministrator::RunStartupScript() succeeded, ");
  448.                     
  449.                     if (resultID != kOSANullScript)
  450.                     {
  451.                         printf("with result: ");
  452.                         err = OSADisplay(gScriptingComponent, resultID, 
  453.                                             typeChar, kOSAModeNull, &displayData);
  454.                         if (err == noErr && displayData.dataHandle)
  455.                         {
  456.                             short    zero = 0;
  457.                             Handle    h = displayData.dataHandle;
  458.                             
  459.                             PtrAndHand(&zero, h, 1);    // shove a zero on the end for stdio
  460.                             HLock(h);
  461.                             printf((char*)*h);
  462.                             HUnlock(h);
  463.                             AEDisposeDesc(&displayData);
  464.                         }
  465.                     }
  466.                     else
  467.                         printf("no result was returned");
  468.                     printf("\n");
  469.                 }
  470.                     
  471.                 OSADispose(gScriptingComponent, startupScript);
  472.                 OSADispose(gScriptingComponent, resultID);
  473.             }
  474.             else
  475.                 printf("Failed to load startup script from file, err = %d\n", err);
  476.         }
  477.         else
  478.             printf("Failed to establish current directory, err = %d\n", err);
  479.         
  480.         fStartupScriptRunning = false;
  481.     }
  482. }
  483.  
  484.  
  485. OSAError TScriptAdministrator::DoScript(AEDesc *scriptDesc, AEDesc *resultDesc)
  486. {
  487.     OSAError        err = errAEEventNotHandled;
  488.  
  489.     if (scriptDesc && (scriptDesc->descriptorType == typeChar
  490.                         || scriptDesc->descriptorType == typeIntlText))
  491.     {
  492.         TScriptableObject*    oldParent = NULL;
  493.         TScriptableObject*    objectContext = NULL;
  494.         OSAID    resultID = kOSANullScript;
  495.         OSAID    useContext = kOSANullScript;
  496.         
  497.         err = GetAttachedScript(NULL, objectContext, oldParent);
  498.         if (objectContext)
  499.             useContext = objectContext->GetObjScript();
  500.         else
  501.             useContext = gScriptAdministrator->GetSharedScript();
  502.             
  503.         err = OSACompileExecute(gScriptingComponent, scriptDesc,
  504.                                 useContext, kOSAModeAlwaysInteract, &resultID);
  505.         
  506.         if (err)
  507.             DumpOSAerrorInfo(gScriptingComponent, err);
  508.         else if (resultID != kOSANullScript)
  509.             err = OSACoerceToDesc(gScriptingComponent, resultID, typeWildCard,
  510.                                      kOSAModeNull, resultDesc);
  511.             
  512.         OSADispose(gScriptingComponent, resultID);
  513.         ReleaseAttachedScript(NULL, oldParent);
  514.     }
  515.     
  516.     return err;
  517. }
  518.  
  519.  
  520. OSAError TScriptAdministrator::SetScriptParent(ComponentInstance scriptingComponent,
  521.                                             OSAID contextID, OSAID newParentID)
  522. {
  523.     OSAError        err = noErr;
  524.     AEDesc            nameDesc;
  525.     DescType        thePropCode = pASParent;
  526.  
  527.     err = AECreateDesc(typeProperty, (Ptr)&thePropCode, 
  528.                         sizeof(thePropCode), &nameDesc);
  529.     if (err == noErr)
  530.     {
  531.         err = OSASetProperty(scriptingComponent, kOSAModeNull,  
  532.                              contextID, &nameDesc, newParentID);
  533.         AEDisposeDesc(&nameDesc);
  534.     }
  535.     if (err)
  536.         printf("::SetScriptParent (%ld->%ld) failed, err = %ld\n", 
  537.                 contextID, newParentID, err);
  538.     
  539.     return err;
  540. }
  541.  
  542.  
  543. OSAError    TScriptAdministrator::GetAttachedScript(TScriptableObject* theObj,
  544.                                                     TScriptableObject* &useObject,
  545.                                                     TScriptableObject* &savedParent)
  546. {
  547.     OSAError        err = noErr;
  548.  
  549. #ifdef qUseOSAinheritance
  550.     useObject = theObj;        // simply use target object's script
  551. #else
  552.     OSAID            theObjScript = kOSANullScript;
  553.     
  554.     if (theObj)
  555.         theObjScript = theObj->GetObjScript();
  556.     if (theObjScript != kOSANullScript)
  557.         err = StartUsing(theObj, savedParent);    // new parent for glob vars script
  558.     else
  559.         err = StartUsing(NULL, savedParent);    // parent is shared handlers
  560.     if (err)
  561.         useObject = NULL;
  562.     else
  563.         useObject = this;    // if OK, return global variables script
  564. #endif
  565.     if (useObject)
  566.         useObject->WalkContextChain();
  567.     return err;
  568. }
  569.  
  570.  
  571. OSAError    TScriptAdministrator::ReleaseAttachedScript(TScriptableObject* theObj,
  572.                                                         TScriptableObject* savedParent)
  573. {
  574.     OSAError        err = noErr;
  575.     
  576. #ifndef qUseOSAinheritance
  577.     err = StopUsing(savedParent);
  578. #endif
  579.     
  580.     return err;
  581. }
  582.  
  583.  
  584. void    TScriptAdministrator::SetSharedScript(OSAID theScriptID)
  585. {
  586.     OSAID oldSharedScript = fSharedScript;
  587.     
  588.     fSharedScript = theScriptID;
  589.     if (oldSharedScript != kOSANullScript)    // should always be so
  590.         OSADispose(gScriptingComponent, oldSharedScript);
  591.     gSimpliFace2->FixUpScriptReferences(NULL);
  592.     this->FixUpScriptReferences(NULL);
  593.     printf("after setting shared handlers script, id=%ld\n", fSharedScript);
  594. }
  595.  
  596.  
  597.  
  598. OSAError    TScriptAdministrator::LoadScriptFromFile(FSSpec *fileSpec, OSAID *theScriptID)
  599. {
  600.     short        fileRef = FSpOpenResFile(fileSpec, fsRdPerm);
  601.     OSAError    err = ResError();
  602.  
  603.     if (err == noErr)
  604.     {
  605.         Handle    h = Get1Resource(kOSAScriptResourceType, 128);
  606.         
  607.         if (h)
  608.         {
  609.             AEDesc    scriptData;
  610.             
  611.             scriptData.descriptorType = typeOSAGenericStorage;
  612.             scriptData.dataHandle = h;
  613.             
  614.             err = OSALoad(gScriptingComponent, &scriptData, kOSAModeNull,
  615.                             theScriptID);
  616.                             
  617.             ReleaseResource(scriptData.dataHandle);
  618.             CloseResFile(fileRef);
  619.             
  620.             return err;
  621.         }
  622.     }
  623.  
  624.     return err;
  625. }
  626.  
  627.  
  628. OSAError    TScriptAdministrator::SaveScriptToFile(FSSpec *fileSpec, OSAID theScriptID)
  629. {
  630.     FSpCreateResFile(fileSpec, 'ToyS', 'osas', smRoman); 
  631.     // ignore errors - let's see if we can open the file, now
  632.     
  633.     short        fileRef = FSpOpenResFile(fileSpec, fsRdPerm);
  634.     OSAError    err = ResError();
  635.  
  636.     if (err == noErr)
  637.     {
  638.         AEDesc    scriptData;
  639.  
  640.         InitAEDescs(&scriptData, kEndOfList);
  641.         
  642.         err = OSAStore(gScriptingComponent, theScriptID, typeOSAGenericStorage, 
  643.                         kOSAModeDontStoreParent, &scriptData);
  644.         
  645.         if (err == noErr && scriptData.dataHandle)
  646.         {
  647.             FInfo        fndrInfo;
  648.             Handle        h = Get1Resource(kOSAScriptResourceType, 128);
  649.             
  650.             if (h)
  651.             {    // delete old script resource
  652.                 RmveResource(h);
  653.                 h = NULL;
  654.             }
  655.             
  656.             AddResource(scriptData.dataHandle, kOSAScriptResourceType, 128, 
  657.                         (ConstStr255Param)"");
  658.             
  659.             err = FSpGetFInfo(fileSpec, &fndrInfo);
  660.             if (err == noErr)
  661.             {
  662.                 fndrInfo.fdType = 'osas';
  663.                 fndrInfo.fdCreator = 'ToyS';
  664.                 err = FSpSetFInfo(fileSpec, &fndrInfo);
  665.             }
  666.         }
  667.         else if (err == noErr)
  668.             err = -194; // addResFailed
  669.  
  670.         CloseResFile(fileRef);
  671.     }
  672.  
  673.     return err;
  674. }
  675.  
  676.  
  677.  
  678. OSAID TScriptAdministrator::GetParentScript()
  679. {
  680.     if (fParentObj)
  681.         return fParentObj->GetObjScript();
  682.     else
  683.         return GetSharedScript();
  684. }    
  685.  
  686.  
  687. /*******************************************************************************
  688. ** PUBLIC Constructor/Destructor
  689. ********************************************************************************/
  690.  
  691. TScriptableObject::TScriptableObject(TScriptableObject* curParent)
  692. {    
  693.     fParentObj = curParent;    // if this is null, parent script is shared handlers
  694.     fAttachedScript = kOSANullScript;
  695.     if (gScriptingComponent)
  696.     {
  697.         // Because SimpliFace2 sets up a static script inheritance hierarchy
  698.         // it needs every scriptable object to have an attached script, even
  699.         // if that script is empty. So, the first thing we do when we create
  700.         // a scriptable object is create an empty script to attach to it.
  701.         // This script will be overwritten when the script property of an
  702.         // object is set.
  703.         // An optional parameter to this constructor is the object's parent
  704.         // object; if it is specified then the script of that object is
  705.         // used to initialise our fCurParent field.
  706.         OSAID newScriptID = kOSANullScript;
  707.         OSAID parentScriptID = GetParentScript();
  708.         AEDesc    contextName;
  709.         InitAEDescs(&contextName, kEndOfList);
  710.             
  711.         printf("creating new object with parent %ld", parentScriptID);
  712.         OSAError err = OSAMakeContext(gScriptingComponent, &contextName,
  713.                                         parentScriptID, &newScriptID);
  714.         if (err)
  715.             printf("; OSAMakeContext failed: err = %ld\n", err);
  716.         else
  717.         {
  718.             fAttachedScript = newScriptID;
  719.             printf("; attached script %ld\n", newScriptID);
  720.         }
  721.         // DisposeAEDescs(&contextName, kEndOfList);
  722.     }
  723. }
  724.  
  725. TScriptableObject::~TScriptableObject(void)
  726. {
  727.     if (fAttachedScript != kOSANullScript && gScriptingComponent)
  728.     {
  729.         OSADispose(gScriptingComponent, fAttachedScript);
  730.     }
  731. }
  732.  
  733.  
  734. OSAError TScriptableObject::SetCurParent(TScriptableObject* theParent)
  735. {
  736.     OSAError    err = noErr;
  737.     OSAID        curParentScriptID = GetParentScript();
  738.     fParentObj = theParent;
  739.     OSAID        newParentScriptID = GetParentScript();
  740.     
  741. #ifdef qUseOSAinheritance
  742.     printf("(using OSA inheritance; property not set) ");
  743. //    OSAID ospecID = GetObjectSpecifierAsScriptValue();
  744. //    if (fAttachedScript != kOSANullScript)
  745. //        err = gScriptAdministrator->SetScriptParent(gScriptingComponent, 
  746. //                                                    fAttachedScript, ospecID);
  747. //    OSADispose(gScriptingComponent, ospecID);
  748. #else
  749.     if (fAttachedScript != kOSANullScript)
  750.         err = gScriptAdministrator->SetScriptParent(gScriptingComponent, 
  751.                                                     fAttachedScript, 
  752.                                                     newParentScriptID);
  753. #endif
  754.     printf("::SetCurParent: script %ld; oldParent %ld; newParent %ld\n",
  755.             fAttachedScript, curParentScriptID, newParentScriptID);
  756.  
  757.     return err;
  758. }
  759.  
  760.  
  761. void TScriptableObject::FixUpScriptReferences(TScriptableObject* theParent)
  762. {
  763.     if (fParentObj == theParent)
  764.     {
  765.         printf("::FixUpScriptReferences: ");
  766.         SetCurParent(fParentObj);
  767.     }
  768. }
  769.  
  770.  
  771. OSAError TScriptableObject::StartUsing(TScriptableObject* newParent, 
  772.                                         TScriptableObject* &oldParent)
  773. {
  774.     OSAError    err = noErr;
  775.     
  776.     oldParent = fParentObj;
  777.     printf("::StartUsing: ");
  778.     err = SetCurParent(newParent);
  779.  
  780.     return err;
  781. }
  782.  
  783.  
  784. OSAError TScriptableObject::StopUsing(TScriptableObject* oldParent)
  785. {
  786.     OSAError    err = noErr;
  787.  
  788.     printf("::StopUsing: ");
  789.     err = SetCurParent(oldParent);
  790.  
  791.     return err;
  792. }
  793.  
  794.  
  795.  
  796. OSErr TScriptableObject::CountElements(DescType desiredClass, long *result)
  797. {
  798.     OSErr             err = errAEEventNotHandled;
  799.     
  800.     return err;
  801. }
  802.  
  803.                                     
  804. OSErr TScriptableObject::CompareWith   (DescType comparisonOperator,
  805.                                     const TScriptableObject *objToCompare,
  806.                                     Boolean *result)
  807. {
  808.     return errAEEventNotHandled;
  809. }
  810.         
  811.         
  812.             
  813. OSErr TScriptableObject::ResolveContainer(TScriptableObject **theContainerObj)
  814. {
  815.     OSErr             err = errAEEventNotHandled;
  816.  
  817.     return err;
  818. }
  819.  
  820.                                     
  821. OSErr TScriptableObject::ResolveElementByName(DescType desiredClass,
  822.                                         CStr255& nameStr,
  823.                                         TScriptableObject **theResultObj)
  824. {
  825.     OSErr             err = errAEEventNotHandled;
  826.  
  827.     return err;
  828. }
  829.  
  830.                                     
  831. OSErr TScriptableObject::ResolveElementByIndex(DescType desiredClass,
  832.                                         short theIndex,
  833.                                         TScriptableObject **theResultObj)
  834. {
  835.     OSErr             err = errAEEventNotHandled;
  836.  
  837.     return err;
  838. }
  839.  
  840.  
  841. // data handling
  842.  
  843. OSErr TScriptableObject::OpenObject(void)
  844. {
  845.     OSErr                 err = errAEEventNotHandled;
  846.     
  847.     printf("TScriptableObject::OpenObject(): err = %d\n", err);
  848.     return err;
  849. }
  850.  
  851. OSErr TScriptableObject::CloseObject(void)
  852. {
  853.     OSErr                 err = errAEEventNotHandled;
  854.  
  855.     return err;
  856. }
  857.                                     
  858. OSErr TScriptableObject::GetData  (AEDesc *result)
  859. {
  860. //    OSErr                 err = AECreateList(NULL, 0, true, result);
  861.     OSErr                 err = errAEEventNotHandled;
  862.         
  863.     return err;
  864. }
  865.                                             
  866. OSErr TScriptableObject::SetData  (const AEDesc *theData)
  867. {
  868.     //     data is AERecord; for each Label of record:
  869.     //        save it as property of object with keyword = propertyID
  870.     OSAError        err = noErr;
  871.     long            numItems = 0;
  872.     
  873.     err = AECountItems(theData, &numItems);
  874.  
  875.     while (err == noErr && numItems > 0)
  876.     {
  877.         AEKeyword        theKeyword;
  878.         AEDesc            theProperty;
  879.         
  880.         InitAEDescs(&theProperty, kEndOfList);
  881.         err = AEGetNthDesc(theData, numItems, typeWildCard, 
  882.                             &theKeyword, &theProperty);
  883.         if (err == noErr && theKeyword != typeNull)
  884.             SetProperty(theKeyword, &theProperty);
  885.         DisposeAEDescs(&theProperty, kEndOfList);
  886.         numItems--;
  887.     }
  888.  
  889.     return err;
  890. }    
  891.  
  892. OSErr TScriptableObject::GetProperty  (DescType propertyID, DescType wantType, AEDesc *result)
  893. {
  894.     OSErr                 err = errAEEventNotHandled;
  895.  
  896.     switch (propertyID)
  897.     {
  898.     case pScript:
  899.         if (fAttachedScript != kOSANullScript)
  900.         {
  901.             printf("TScriptableObject::GetProperty(): get script as type '%.4s'\n",
  902.                     (char*)&wantType);
  903.             if (wantType == typeChar || wantType == typeIntlText)
  904.             {    // if caller wants text, we need to de-compile the script
  905.                 err = (OSErr)OSAGetSource(gScriptingComponent, fAttachedScript, 
  906.                                             wantType, result);
  907.             }
  908.             else
  909.             {
  910.                 if (wantType == typeWildCard)
  911.                     wantType = typeOSAGenericStorage;
  912.                     
  913.                 err = (OSErr)OSAStore(gScriptingComponent, fAttachedScript, 
  914.                                     wantType, kOSAModeDontStoreParent, result);
  915.             }
  916.         }
  917.         break;
  918.     }
  919.     
  920.     return err;
  921. }
  922.                                             
  923. OSErr TScriptableObject::SetProperty  (DescType propertyID, const AEDesc *theData)
  924. {
  925.     OSAError                err = errAEEventNotHandled;
  926.  
  927.     switch (propertyID)
  928.     {
  929.     case pScript:
  930.         OSAID theValueID = kOSANullScript;
  931.         if (theData->descriptorType == typeChar
  932.             || theData->descriptorType == typeIntlText)
  933.             err = OSACompile(gScriptingComponent, theData, 
  934.                              kOSAModeCompileIntoContext, &theValueID);
  935.         else // it it's not text, we assume the script is already compiled
  936.         {
  937.             err = OSALoad(gScriptingComponent, theData, 
  938.                             kOSAModeNull, &theValueID);
  939.             // the following section strips any existing parent script:
  940.             // (it did not exist in version 1 of SimpliFace)
  941.             if (err == noErr) 
  942.             { 
  943.                 AEDesc        newData;
  944.                 err = OSAStore(gScriptingComponent, theValueID, 
  945.                                     typeOSAGenericStorage, 
  946.                                     kOSAModeDontStoreParent, 
  947.                                     &newData);
  948.                 if (err == noErr) 
  949.                 {
  950.                     OSADispose(gScriptingComponent, theValueID);
  951.                     theValueID = kOSANullScript;
  952.                     err = (OSErr)OSALoad(gScriptingComponent, &newData, 
  953.                                                 kOSAModeNull, &theValueID);
  954.                     AEDisposeDesc(&newData);
  955.                 }
  956.             }
  957.         }
  958.         if (err == noErr)
  959.         {    
  960.             if (fAttachedScript != kOSANullScript)
  961.                 OSADispose(gScriptingComponent, fAttachedScript);
  962.             fAttachedScript = theValueID;
  963.             err = SetCurParent(fParentObj);
  964.             // this fixes up references in any object that
  965.             // has current object as it's parent:
  966.             this->FixUpScriptReferences(this);
  967.             
  968.             printf("set object's attached script, id=%ld, parent=%ld, err=%ld\n",
  969.                     fAttachedScript, GetParentScript(), err);
  970.         }
  971.         break;
  972.     }
  973.     
  974.     return (OSErr)err;
  975. }    
  976.  
  977.  
  978. OSErr TScriptableObject::CreateNewElement    (DescType desiredClass,
  979.                                         DescType position,
  980.                                         AEDesc *theData,
  981.                                         AERecord *theProperties,
  982.                                         TScriptableObject *theContainerObj,
  983.                                         TScriptableObject **theNewObj)
  984. {
  985.     OSErr             err = errAEEventNotHandled;
  986.  
  987.     return err;
  988. }    
  989.  
  990.  
  991. OSErr TScriptableObject::DeleteObject  (void)
  992. {
  993.     return errAEEventNotHandled;
  994. }
  995.  
  996.  
  997. OSErr TScriptableObject::GetObjectSpecifier  (AEDesc *result)
  998. {
  999.     return errAEEventNotHandled;
  1000. }    
  1001.  
  1002.  
  1003. OSAID TScriptableObject::GetObjectSpecifierAsScriptValue()
  1004. {
  1005.     OSAError         err = noErr;
  1006.     AEDesc            resultDesc;
  1007.     OSAID            theValueID = kOSANullScript;
  1008.  
  1009.     InitAEDescs(&resultDesc, kEndOfList);
  1010.  
  1011.     err = GetObjectSpecifier(&resultDesc);
  1012.     if (!err)
  1013.         err = OSACoerceFromDesc(gScriptingComponent, &resultDesc, 
  1014.                                 kOSAModeNull, &theValueID);
  1015.  
  1016.     DisposeAEDescs(&resultDesc, kEndOfList);
  1017.     
  1018.     return theValueID;
  1019. }    
  1020.  
  1021.  
  1022. OSErr TScriptableObject::GetTargetObjectSpecifier  (EventRecord& theEvent, AEDesc *result)
  1023. {
  1024.     return errAEEventNotHandled;
  1025. }    
  1026.  
  1027.  
  1028. TScriptableObject* TScriptableObject::GetParentObj()
  1029. {
  1030.     return fParentObj;
  1031. }    
  1032.  
  1033.  
  1034. OSAID TScriptableObject::GetParentScript()
  1035. {
  1036.     if (fParentObj)
  1037.         return fParentObj->GetObjScript();
  1038.     else if (gScriptAdministrator)
  1039.         return gScriptAdministrator->GetSharedScript();
  1040.     else
  1041.         return kOSANullScript;
  1042. }    
  1043.  
  1044.  
  1045. void TScriptableObject::WalkContextChain(short depth)
  1046. {
  1047.     if (depth == 0)
  1048.         printf("Current script context chain:\n");
  1049.     else
  1050.     {
  1051.         short i = depth;
  1052.         while (i > 0)
  1053.         {
  1054.             printf("  ");
  1055.             i--;
  1056.         }
  1057.     }
  1058.     printf(" [%d]: scriptID = %ld, parentID = %ld\n", 
  1059.             depth, GetObjScript(), GetParentScript());
  1060.     if (fParentObj)
  1061.         fParentObj->WalkContextChain(depth+1);
  1062. }
  1063.